home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / IPHDR.C < prev    next >
C/C++ Source or Header  |  1997-08-18  |  5KB  |  186 lines

  1. /* IP header conversion routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "ip.h"
  7.  
  8. #if !defined(_lint)
  9. static char rcsid[] OPTIONAL = "$Id: iphdr.c,v 1.13 1997/08/19 01:19:22 root Exp root $";
  10. #endif
  11.  
  12.  
  13. /* Convert IP header in host format to network mbuf
  14.  * If cflag != 0, take checksum from structure,
  15.  * otherwise compute it automatically.
  16.  */
  17. struct mbuf *
  18. htonip (ip, data, cflag)
  19. register struct ip *ip;
  20. struct mbuf *data;
  21. int cflag;
  22. {
  23. int16 hdr_len;
  24. struct mbuf *bp;
  25. register unsigned char *cp;
  26. int16 fl_offs;
  27.  
  28.     hdr_len = (int16) (int) (IPLEN + ip->optlen);
  29.     if (hdr_len > IPLEN + IP_MAXOPT)
  30.         hdr_len = IPLEN + IP_MAXOPT;
  31.     if ((bp = pushdown (data, hdr_len)) == NULLBUF) {
  32.         free_p (data);
  33.         return NULLBUF;
  34.     }
  35.     cp = bp->data;
  36.  
  37.     *cp++ = (char) ((ip->version << 4) | (hdr_len >> 2));    /*lint !e701 */
  38.     *cp++ = uchar(ip->tos);
  39.     cp = put16 (cp, ip->length);
  40.     cp = put16 (cp, ip->id);
  41.     fl_offs = ip->offset >> 3;
  42.     if (ip->flags.congest)
  43.         fl_offs |= 0x8000;
  44.     if (ip->flags.df)
  45.         fl_offs |= 0x4000;
  46.     if (ip->flags.mf)
  47.         fl_offs |= 0x2000;
  48.  
  49.     cp = put16 (cp, fl_offs);
  50.     *cp++ = uchar(ip->ttl);
  51.     *cp++ = uchar(ip->protocol);
  52.     if (cflag) {
  53.         /* Use checksum from host structure */
  54.         cp = put16 (cp, ip->checksum);
  55.     } else {
  56.         /* Clear checksum for later recalculation */
  57.         *cp++ = 0;
  58.         *cp++ = 0;
  59.     }
  60.     cp = put32 (cp, ip->source);
  61.     cp = put32 (cp, ip->dest);
  62.     if (ip->optlen != 0)
  63.         memcpy (cp, ip->options, (unsigned int) (int) min (ip->optlen, IP_MAXOPT));
  64.  
  65.     /* If requested, recompute checksum and insert into header */
  66.     if (!cflag)
  67.         (void) put16 (&bp->data[10], cksum (NULLHEADER, bp, hdr_len));
  68.  
  69.     return bp;
  70. }
  71.  
  72.  
  73. /* Extract an IP header from mbuf */
  74. int
  75. ntohip (ip, bpp)
  76. register struct ip *ip;
  77. struct mbuf **bpp;
  78. {
  79. int ihl;
  80. int16 fl_offs;
  81. char ipbuf[IPLEN];
  82.  
  83.     if (pullup (bpp, (unsigned char *) ipbuf, IPLEN) != IPLEN)
  84.         return -1;
  85.  
  86.     ip->version = (ipbuf[0] >> 4) & 0xf;    /*lint !e702 */
  87.     ip->tos = ipbuf[1];
  88.     ip->length = get16 (&ipbuf[2]);
  89.     ip->id = get16 (&ipbuf[4]);
  90.     fl_offs = get16 (&ipbuf[6]);
  91.     ip->offset = (fl_offs & 0x1fff) << 3;
  92.     ip->flags.mf = (fl_offs & 0x2000) ? 1 : 0;
  93.     ip->flags.df = (fl_offs & 0x4000) ? 1 : 0;
  94.     ip->flags.congest = (fl_offs & 0x8000) ? 1 : 0;
  95.     ip->ttl = ipbuf[8];
  96.     ip->protocol = ipbuf[9];
  97.     ip->checksum = get16 (&ipbuf[10]);
  98.     ip->source = get32 (&ipbuf[12]);
  99.     ip->dest = get32 (&ipbuf[16]);
  100.  
  101.     ihl = (ipbuf[0] & 0xf) << 2;
  102.     if (ihl < IPLEN) {
  103.         /* Bogus packet; header is too short */
  104.         ip->optlen = 0;
  105.         return -1;
  106.     }
  107.     if ((ip->optlen = (char) (ihl - IPLEN)) != 0) {
  108.         if (pullup (bpp, (unsigned char *) ip->options, (int16) ((int) ip->optlen)) < ip->optlen)
  109.             return -1;
  110.     }
  111.     return ihl;
  112. }
  113.  
  114.  
  115. /* Perform end-around-carry adjustment */
  116. int16
  117. eac (sum)
  118. register int32 sum;        /* Carries in high order 16 bits */
  119. {
  120. register int16 csum;
  121.  
  122.     while ((csum = sum >> 16) != 0)        /*lint !e704 */
  123.         sum = csum + (sum & 0xffffL);
  124.     return (int16) (sum & 0xffffL);    /* Chops to 16 bits */
  125. }
  126.  
  127.  
  128. /* Checksum a mbuf chain, with optional pseudo-header */
  129. int16
  130. cksum (struct pseudo_header * ph, register struct mbuf * m, int16 len)
  131. {
  132. register int16 cnt, total;
  133. register int32 sum = 0L, csum;
  134. register char *up;
  135. int16 csum1;
  136. int swap = 0;
  137.  
  138.     /* Sum pseudo-header, if present */
  139.     if (ph != NULLHEADER) {
  140.         sum = hiword (ph->source);
  141.         sum += loword (ph->source);
  142.         sum += hiword (ph->dest);
  143.         sum += loword (ph->dest);
  144.         sum += uchar (ph->protocol);
  145.         sum += ph->length;
  146.     }
  147.     /* Now do each mbuf on the chain */
  148.     for (total = 0; m != NULLBUF && total < len; m = m->next) {
  149.         cnt = min (m->cnt, len - total);
  150.         up = (char *) m->data;
  151.         csum = 0;
  152.  
  153.         if (((long) up) & 1) {
  154.             /* Handle odd leading byte */
  155.             if (swap)
  156.                 csum = uchar (*up++);
  157.             else
  158.                 csum = (int16) (uchar (*up++) << 8);
  159.             cnt--;
  160.             swap = !swap;
  161.         }
  162.         if (cnt > 1) {
  163.             /* Have the primitive checksumming routine do most of
  164.              * the work. At this point, up is guaranteed to be on
  165.              * a short boundary
  166.              */
  167.             csum1 = lcsum ((unsigned short *) up, (int16) (cnt >> 1));
  168.             if (swap)
  169.                 csum1 = (int16) ((csum1 << 8) | (csum1 >> 8));
  170.             csum += csum1;
  171.         }
  172.         /* Handle odd trailing byte */
  173.         if (cnt & 1) {
  174.             if (swap)
  175.                 csum += uchar (up[--cnt]);
  176.             else
  177.                 csum += (int16) (uchar (up[--cnt]) << 8);
  178.             swap = !swap;
  179.         }
  180.         sum += csum;
  181.         total += m->cnt;
  182.     }
  183.     /* Do final end-around carry, complement and return */
  184.     return (int16) (~eac (sum) & 0xffff);
  185. }
  186.